package org.springmvc.dao;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springmvc.model.BaseEntity;
import org.springmvc.pagination.Page;
import org.springmvc.pagination.PageUtill;
import org.springmvc.pagination.Pageable;

import javax.annotation.Resource;
import java.lang.reflect.ParameterizedType;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 基础DAO
 * @param <E> 实体
 * @author 唐家林
 * @time 2014年9月5日
 */
public abstract class AbstractBaseDao<E extends BaseEntity> {

    @Resource(name = "sessionFactory")
    private SessionFactory sessionFactory;

    /**
     * 在同一线程获取Session
     * @return 返回获取到的Session
     */
    protected Session getSession() {
        return sessionFactory.getCurrentSession();
    }

    /**
     * 获得SessionFactory
     * @return 返回SessionFactory
     */
    protected SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    /**
     * 创建一个新的Session
     * <p>
     * PS:使用该方法获得Session之后必须手动关闭
     * @return Session 返回创建的Session
     */
    protected Session openSession() {
        return sessionFactory.openSession();
    }

    /**
     * 实体类型
     */
    private Class<E> entityClass;

    /**
     * 获取实体类型
     * @return Class<E>
     */
    protected Class<E> getEntityClass() {
        return entityClass;
    }

    /**
     * 构造方法
     */
    @SuppressWarnings("unchecked")
    public AbstractBaseDao() {
        ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
        this.entityClass = (Class<E>) type.getActualTypeArguments()[0];
    }

    /**
     * 获取总记录数
     * @return 记录总数
     */
    public Long countAll() {
        return countAll(entityClass);
    }

    /**
     * 获取总记录数
     * @param entityClass 实体类型
     * @return 记录总数
     */
    protected Long countAll(Class<E> entityClass) {
        String hql = "SELECT COUNT(_table.id) FROM " + entityClass.getName() + " AS _table";
        Object[] values = null;
        return count(QueryType.HQL, hql, values);
    }

    /**
     * 获取总记录数
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param list      参数值集合
     * @return 记录总数
     */
    protected Long count(QueryType queryType, String ql, List<Object> list) {
        if (ql == null) {
            return 0L;
        }
        String target = ql.substring(0, ql.toUpperCase().indexOf("FROM"));
        ql = ql.replace(target, "SELECT COUNT(*) ");
        Query q = createQuery(queryType, ql);
        int size = 0;
        if (list != null && (size = list.size()) > 0) {
            for (int i = 0; i < size; i++) {
                q.setParameter(i, list.get(i));
            }
        }
        Object count = q.uniqueResult();
        return Long.valueOf(String.valueOf(count));
    }

    /**
     * 获取总记录数
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @return 记录总数
     */
    protected Long count(QueryType queryType, String ql, Map<String, Object> condition) {
        if (ql == null) {
            return 0L;
        }
        String target = ql.substring(0, ql.toUpperCase().indexOf("FROM"));
        ql = ql.replace(target, "SELECT COUNT(*) ");
        Query q = createQuery(queryType, ql);
        if (condition != null && !condition.isEmpty()) {
            q.setProperties(condition);
        }
        Object count = q.uniqueResult();
        return Long.valueOf(String.valueOf(count));
    }

    /**
     * 获取总记录数
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param values    一个或多个参数值
     * @return 记录总数
     */
    protected Long count(QueryType queryType, String ql, Object... values) {
        if (ql == null) {
            return 0L;
        }
        String target = ql.substring(0, ql.toUpperCase().indexOf("FROM"));
        ql = ql.replace(target, "SELECT COUNT(*) ");
        Query q = createQuery(queryType, ql);
        int length = 0;
        if (values != null && (length = values.length) > 0) {
            for (int i = 0; i < length; i++) {
                q.setParameter(i, values[i]);
            }
        }
        Object count = q.uniqueResult();
        return Long.valueOf(String.valueOf(count));
    }

    /**
     * 执行操作语句
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param list      参数值集合
     * @return 执行结果
     */
    protected int execute(QueryType queryType, String ql, List<Object> list) {
        Query q = createQuery(queryType, ql);
        int size = 0;
        if (list != null && (size = list.size()) > 0) {
            for (int i = 0; i < size; i++) {
                q.setParameter(i, list.get(i));
            }
        }
        return q.executeUpdate();
    }

    /**
     * 执行操作语句
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param condition 查询条件键值对集合
     * @return 执行结果
     */
    protected int execute(QueryType queryType, String ql, Map<String, Object> condition) {
        Query q = createQuery(queryType, ql);
        if (condition != null && !condition.isEmpty()) {
            q.setProperties(condition);
        }
        return q.executeUpdate();
    }

    /**
     * 执行操作语句
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param values    一个或多个参数值
     * @return 执行结果
     */
    protected int execute(QueryType queryType, String ql, Object... values) {
        Query q = createQuery(queryType, ql);
        int length = 0;
        if (values != null && (length = values.length) > 0) {
            for (int i = 0; i < length; i++) {
                q.setParameter(i, values[i]);
            }
        }
        return q.executeUpdate();
    }

    /**
     * 查询返回单个实体对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param list      一个或多个参数值
     * @return 查询结果
     */
    @SuppressWarnings("unchecked")
    protected E uniqueQuery(QueryType queryType, String ql, List<Object> list) {
        Query q = createQuery(queryType, ql);
        int size = 0;
        if (list != null && (size = list.size()) > 0) {
            for (int i = 0; i < size; i++) {
                q.setParameter(i, list.get(i));
            }
        }
        return (E) q.uniqueResult();
    }

    /**
     * 查询返回单个实体对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param condition 查询条件键值对集合
     * @return 查询结果
     */
    @SuppressWarnings("unchecked")
    protected E uniqueQuery(QueryType queryType, String ql, Map<String, Object> condition) {
        Query q = createQuery(queryType, ql);
        if (condition != null && !condition.isEmpty()) {
            q.setProperties(condition);
        }
        return (E) q.uniqueResult();
    }

    /**
     * 查询返回单个实体对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param values    一个或多个参数值
     * @return 查询结果
     */
    @SuppressWarnings("unchecked")
    protected E uniqueQuery(QueryType queryType, String ql, Object... values) {
        Query q = createQuery(queryType, ql);
        int length = 0;
        if (values != null && (length = values.length) > 0) {
            for (int i = 0; i < length; i++) {
                q.setParameter(i, values[i]);
            }
        }
        return (E) q.uniqueResult();
    }

    /**
     * 添加实体
     * @param e 期望添加的实体对象实例
     * @return 返回添加后的实体对象实例
     */
    public E save(E e) {
        Date date = new Date();
        e.setCreateTime(date);
        e.setUpdateTime(date);
        e.setIsDeleted(false);
        getSession().save(e);
        return e;
    }

    /**
     * 修改实体
     * @param e 期望修改的实体对象实例
     * @return 返回修改后的实体对象实例
     */
    public E update(E e) {
        e.setUpdateTime(new Date());
        e.setIsDeleted(false);
        getSession().update(e);
        return e;
    }

    /**
     * 物理删除单实体
     * @param entityClass 实体类型
     * @param id          期望删除的实体主键
     * @return 返回删除条数
     */
    protected int delete(Class<E> entityClass, Integer id) {
        String hql = "DELETE FROM " + entityClass.getName() + " AS _table WHERE _table.id = :id";
        Query q = getSession().createQuery(hql);
        q.setParameter("id", id);
        return q.executeUpdate();
    }

    /**
     * 物理删除多实体
     * @param entityClass 期望删除的实体类型
     * @param ids         期望删除的多个实体主键
     * @return 返回删除条数
     */
    protected int delete(Class<E> entityClass, Integer[] ids) {
        String hql = "DELETE FROM " + entityClass.getName() + " AS _table WHERE _table.id IN ( :ids )";
        Query q = getSession().createQuery(hql);
        q.setParameterList("ids", ids);
        return q.executeUpdate();
    }

    /**
     * 物理删除单实体
     * @param e 期望删除的实体对象实例
     */
    public void delete(E e) {
        delete(entityClass, e.getId());
        // getSession().delete(e);
    }

    /**
     * 物理删除单实体
     * @param id 期望删除的实体主键
     * @return 返回删除条数
     */
    public int delete(Integer id) {
        return delete(entityClass, id);
    }

    /**
     * 物理删除多实体
     * @param ids 期望删除的多个实体主键
     * @return 返回删除条数
     */
    public int delete(Integer[] ids) {
        return delete(entityClass, ids);
    }

    /**
     * 物理删除多实体
     * @param es 期望删除的多个实体对象实例
     */
    public void delete(List<E> es) {
        int size = 0;
        if (es == null || (size = es.size()) <= 0) return;
        Integer[] ids = new Integer[size];
        for (int index = 0; index < size; index++) {
            ids[index] = es.get(index).getId();
        }
        delete(entityClass, ids);
        // for (Iterator<E> iterator = es.iterator(); iterator.hasNext();) {
        // delete(iterator.next());
        // }
    }

    /**
     * 物理删除所有实体
     * @return 返回删除的行数
     */
    public int deleteAll() {
        return deleteAll(entityClass);
    }

    /**
     * 物理删除所有实体
     * @param entityClass 实体类型
     * @return 返回删除的行数
     */
    protected int deleteAll(Class<E> entityClass) {
        String hql = "DELETE FROM " + entityClass.getName();
        Query query = getSession().createQuery(hql);
        return query.executeUpdate();
    }

    /**
     * 获取所有实体
     * @return 返回所有实体对象实例集合
     */
    public List<E> findAll() {
        return findAll(entityClass);
    }

    /**
     * 获取所有实体
     * @param entityClass 实体类型
     * @return 返回所有指定实体类型的实体对象实例集合
     */
    protected List<E> findAll(Class<E> entityClass) {
        String hql = "SELECT _table FROM " + entityClass.getName()
                + " AS _table ORDER BY _table.id ASC";
        Object[] values = null;
        return find(QueryType.HQL, hql, values);
    }

    /**
     * 分页设置
     * @param q        查询对象
     * @param pageNum  页码
     * @param pageSize 每一页显示记录数
     * @return 返回查询对象
     */
    protected Query settingPagination(Query q, int pageNum, int pageSize) {
        if (pageNum > 0 && pageSize > 0) {
            q.setMaxResults(pageSize);
            q.setFirstResult((pageNum - 1) * pageSize);
        }
        return q;
    }

    /**
     * 查询对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param pageNum   页码
     * @param pageSize  每一页显示记录数
     * @param list      参数值集合
     * @return 查询结果集
     */
    @SuppressWarnings("unchecked")
    protected List<E> find(QueryType queryType, String ql, int pageNum, int pageSize, List<Object> list) {
        Query q = createQuery(queryType, ql);
        int size = 0;
        if (list != null & (size = list.size()) > 0) {
            for (int i = 0; i < size; i++) {
                q.setParameter(i, list.get(i));
            }
        }

        settingPagination(q, pageNum, pageSize);
        return q.list();
    }

    /**
     * 查询对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param pageNum   页码
     * @param pageSize  每一页显示记录数
     * @param condition 查询条件键值对集合
     * @return 查询结果集
     */
    @SuppressWarnings("unchecked")
    protected List<E> find(QueryType queryType, String ql, int pageNum, int pageSize, Map<String, Object> condition) {
        Query q = createQuery(queryType, ql);
        if (condition != null && (!condition.isEmpty())) {
            q.setProperties(condition);
        }

        settingPagination(q, pageNum, pageSize);
        return q.list();
    }

    /**
     * 查询对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param pageNum   页码
     * @param pageSize  每一页显示记录数
     * @param values    一个或多个参数值
     * @return 查询结果集
     */
    @SuppressWarnings("unchecked")
    protected List<E> find(QueryType queryType, String ql, int pageNum, int pageSize, Object... values) {
        Query q = createQuery(queryType, ql);
        int length = 0;
        if (values != null && (length = values.length) > 0) {
            for (int i = 0; i < length; i++) {
                q.setParameter(i, values[i]);
            }
        }

        settingPagination(q, pageNum, pageSize);
        return q.list();
    }

    /**
     * 查询对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param list      参数值集合
     * @return 查询结果集
     */
    protected List<E> find(QueryType queryType, String ql, List<Object> list) {
        return find(queryType, ql, -1, -1, list);
    }

    /**
     * 查询对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param condition 查询条件键值对集合
     * @return 查询结果集
     */
    protected List<E> find(QueryType queryType, String ql, Map<String, Object> condition) {
        return find(queryType, ql, -1, -1, condition);
    }

    /**
     * 查询对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param values    一个或多个参数值
     * @return 查询结果集
     */
    protected List<E> find(QueryType queryType, String ql, Object... values) {
        return find(queryType, ql, -1, -1, values);
    }

    /**
     * 查询对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param pageable  分页请求抽象接口
     * @param list      参数值集合
     * @return 查询结果集
     */
    protected Page<E> find(QueryType queryType, String ql, Pageable pageable, List<Object> list) {
        Page<E> page = PageUtill.newPageInstance();
        page.setRecords(find(queryType, ql, pageable.getPage(), pageable.getRows(), list));
        page.setTotal(count(queryType, ql, list));
        return page;
    }

    /**
     * 查询对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param pageable  分页请求抽象接口
     * @param condition 查询条件键值对集合
     * @return 查询结果集
     */
    protected Page<E> find(QueryType queryType, String ql, Pageable pageable, Map<String, Object> condition) {
        Page<E> page = PageUtill.newPageInstance();
        page.setRecords(find(queryType, ql, pageable.getPage(), pageable.getRows(), condition));
        page.setTotal(count(queryType, ql, condition));
        return page;
    }

    /**
     * 查询对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param pageable  分页请求抽象接口
     * @param values    一个或多个参数值
     * @return 查询结果集
     */
    protected Page<E> find(QueryType queryType, String ql, Pageable pageable, Object... values) {
        Page<E> page = PageUtill.newPageInstance();
        page.setPage(pageable.getPage()).setRows(pageable.getRows());
        page.setRecords(find(queryType, ql, pageable.getPage(), pageable.getRows(), values));
        page.setTotal(count(queryType, ql, values));
        return page;
    }

    /**
     * 查询对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param pageNum   页码
     * @param pageSize  每一页显示记录数
     * @param values    一个或多个参数值
     * @return 查询结果集
     */
    @SuppressWarnings("unchecked")
    protected List<Map<String, Object>> findForMap(QueryType queryType, String ql, int pageNum, int pageSize, Object... values) {
        Query q = createQuery(queryType, ql);
        int length = 0;
        if (values != null && (length = values.length) > 0) {
            for (int i = 0; i < length; i++) {
                q.setParameter(i, values[i]);
            }
        }

        settingPagination(q, pageNum, pageSize);
        return q.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP).list();
    }

    /**
     * 查询对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param pageNum   页码
     * @param pageSize  每一页显示记录数
     * @param condition 查询条件键值对集合
     * @return 查询结果集
     */
    @SuppressWarnings("unchecked")
    protected List<Map<String, Object>> findForMap(QueryType queryType, String ql, int pageNum, int pageSize, Map<String, Object> condition) {
        Query q = createQuery(queryType, ql);
        if (condition != null && (!condition.isEmpty())) {
            q.setProperties(condition);
        }

        settingPagination(q, pageNum, pageSize);
        return q.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP).list();
    }

    /**
     * 查询对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param pageable  分页请求抽象接口
     * @param condition 查询条件键值对集合
     * @return 查询结果集
     */
    @SuppressWarnings("unchecked")
    protected List<Map<String, Object>> findForMap(QueryType queryType, String ql, Map<String, Object> condition) {
        Query q = createQuery(queryType, ql);
        if (condition != null && (!condition.isEmpty())) {
            q.setProperties(condition);
        }

        return q.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP).list();
    }

    /**
     * 查询对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param values    一个或多个参数值
     * @return 查询结果集
     */
    protected List<Map<String, Object>> findForMap(QueryType queryType, String ql, Object... values) {
        return findForMap(queryType, ql, -1, -1, values);
    }

    /**
     * 查询对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param pageable  分页请求抽象接口
     * @param condition 查询条件键值对集合
     * @return 查询结果集
     */
    protected Page<Map<String, Object>> findForMap(QueryType queryType, String ql, Pageable pageable, Map<String, Object> condition) {
        Page<Map<String, Object>> page = PageUtill.newPageInstance();
        page.setRecords(findForMap(queryType, ql, pageable.getPage(), pageable.getRows(), condition));
        page.setTotal(count(queryType, ql, condition));
        return page;
    }

    /**
     * 查询对象
     * @param queryType 查询类型.HQL/SQL;参见枚举:{@link org.springmvc.dao.AbstractBaseDao.QueryType}
     * @param ql        HQL/SQL语句.必须使用queryType指定的类型
     * @param pageable  分页请求抽象接口
     * @param values    一个或多个参数值
     * @return 查询结果集
     */
    protected Page<Map<String, Object>> findForMap(QueryType queryType, String ql, Pageable pageable, Object... values) {
        Page<Map<String, Object>> page = PageUtill.newPageInstance();
        page.setRecords(findForMap(queryType, ql, pageable.getPage(), pageable.getRows(), values));
        page.setTotal(count(queryType, ql, values));
        return page;
    }

    /**
     * 获取指定实体类型的实体对象实例
     * @param entityClass 实体类型
     * @param id          实体主键
     * @return 返回获取的实体对象实例
     */
    @SuppressWarnings("unchecked")
    protected E get(Class<E> entityClass, Integer id) {
        if (id == null) { return null; }
        return (E) getSession().get(entityClass, id);
    }

    /**
     * 获取实体对象实例
     * @param id 实体主键
     * @return 返回获取的实体对象实例
     */
    public E get(Integer id) {
        return get(entityClass, id);
    }

    /**
     * 逻辑删除单实体
     * @param entityClass 实体类型
     * @param id          期望删除的实体主键
     */
    protected void logicDelete(Class<E> entityClass, Integer id) {
        logicDelete(get(entityClass, id));
    }

    /**
     * 逻辑删除多实体
     * @param entityClass 实体类型
     * @param ids         期望删除的多个实体主键
     */
    protected void logicDelete(Class<E> entityClass, Integer[] ids) {
        for (Integer id : ids) {
            logicDelete(entityClass, id);
        }
    }

    /**
     * 逻辑删除单实体
     * @param e 期望删除的实体对象实例
     */
    public void logicDelete(E e) {
        e.setDeleteTime(new Date());
        e.setIsDeleted(true);
        getSession().update(e);
    }

    /**
     * 逻辑删除单实体
     * @param id 期望删除的实体主键
     */
    public void logicDelete(Integer id) {
        logicDelete(entityClass, id);
    }

    /**
     * 逻辑删除多实体
     * @param ids 期望删除的多个实体主键
     */
    public void logicDelete(Integer[] ids) {
        logicDelete(entityClass, ids);
    }

    /**
     * 逻辑删除多实体
     * @param es 希望删除的多个实体对象实例
     */
    public void logicDelete(List<E> es) {
        if (null == es || es.size() <= 0) return;
        for (Iterator<E> iterator = es.iterator(); iterator.hasNext(); ) {
            logicDelete(iterator.next());
        }
    }

    /**
     * 恢复逻辑删除的单实体
     * @param entityClass 实体类型
     * @param id          期望删除的实体主键
     */
    protected void disLogicDelete(Class<E> entityClass, Integer id) {
        disLogicDelete(get(entityClass, id));
    }

    /**
     * 恢复逻辑删除的多实体
     * @param entityClass 实体类型
     * @param ids         期望删除的多个实体主键
     */
    protected void disLogicDelete(Class<E> entityClass, Integer[] ids) {
        for (Integer id : ids) {
            disLogicDelete(entityClass, id);
        }
    }

    /**
     * 恢复逻辑删除的单实体
     * @param e 期望删除的实体对象实例
     */
    public void disLogicDelete(E e) {
        e.setDeleteTime(new Date());
        e.setIsDeleted(false);
        getSession().update(e);
    }

    /**
     * 恢复逻辑删除的单实体
     * @param id 期望删除的实体主键
     */
    public void disLogicDelete(Integer id) {
        disLogicDelete(entityClass, id);
    }

    /**
     * 恢复逻辑删除的多实体
     * @param ids 期望删除的多个实体主键
     */
    public void disLogicDelete(Integer[] ids) {
        disLogicDelete(entityClass, ids);
    }

    /**
     * 恢复逻辑删除的多实体
     * @param es 希望删除的多个实体对象实例
     */
    public void disLogicDelete(List<E> es) {
        if (null == es || es.size() <= 0) return;
        for (Iterator<E> iterator = es.iterator(); iterator.hasNext(); ) {
            disLogicDelete(iterator.next());
        }
    }

    /**
     * 创建查询对象
     * @param querytype 查询类型
     * @param ql        查询语句
     * @return 返回查询对象
     */
    protected Query createQuery(QueryType querytype, String ql) {
        if (querytype == null) throw new IllegalArgumentException("未指定查询类型");
        Session session = getSession();
        Query q = null;
        switch (querytype) {
            case HQL:
                q = session.createQuery(ql);
                break;
            case SQL:
                q = session.createSQLQuery(ql);
                break;
            default:
                q = session.createQuery(ql);
                break;
        }
        return q;
    }

    /**
     * 创建Criteria对象
     * @return 返回Criteria
     */
    protected Criteria createCriteria() {
        return createCriteria(entityClass);
    }

    /**
     * 创建Criteria对象
     * @param entityClass 实体类型
     * @return 返回Criteria
     */
    protected Criteria createCriteria(Class<E> entityClass) {
        return getSession().createCriteria(entityClass);
    }

    /**
     * 查询类型枚举
     * @author 唐家林
     * @time 2015年6月22日
     */
    public enum QueryType {
        HQL, SQL
    }
}